package cn.schoolwow.quickdao.module.database.dml.instance.flow.common;

import cn.schoolwow.quickdao.domain.database.dml.UpdateType;
import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.dml.common.domain.ManipulationOption;
import cn.schoolwow.quickflow.domain.FlowContext;
import cn.schoolwow.quickflow.flow.BusinessFlow;
import org.apache.commons.lang3.Validate;

public class SetInstanceUniqueTypeFlow implements BusinessFlow {
    @Override
    public void executeBusinessFlow(FlowContext flowContext) throws Exception {
        ManipulationOption manipulationOption = flowContext.checkInstanceData(ManipulationOption.class);
        Entity entity = (Entity) flowContext.checkData("entity");

        if(null!=manipulationOption.updateType){
            flowContext.putInstanceData(manipulationOption.updateType);
        }else if(!manipulationOption.uniqueFieldNames.isEmpty()){
            flowContext.putInstanceData(UpdateType.UpdateByUniqueFieldName);
        }else if(!entity.uniqueProperties.isEmpty()){
            flowContext.putInstanceData(UpdateType.UpdateByUniqueKey);
        }else if(null!=entity.id){
            flowContext.putInstanceData(UpdateType.UpdateById);
        }else{
            throw new IllegalArgumentException("设置判断实例唯一约束失败!" +
                    "请排查以下原因!" +
                    "1:未调用updateType方法" +
                    "2:未指定唯一字段列表" +
                    ",3:实例未指定唯一性约束" +
                    ",4:实例未指定id字段!" +
                    "涉及类名:" + entity.clazz.getName());
        }

        checkUpdateType(flowContext);
        manipulationOption.returnGeneratedKeys = false;
    }

    @Override
    public String name() {
        return "设置判断实例是否存在的比较类型";
    }

    private void checkUpdateType(FlowContext flowContext){
        UpdateType updateType = flowContext.checkInstanceData(UpdateType.class);
        Entity entity = flowContext.checkData("entity", Entity.class);
        ManipulationOption manipulationOption = flowContext.checkInstanceData(ManipulationOption.class);

        switch (updateType){
            case UpdateByUniqueFieldName:{
                Validate.notEmpty(manipulationOption.uniqueFieldNames, "未指定唯一字段列表!实体类:"+entity.clazz.getName());
            }break;
            case UpdateByUniqueKey:{
                int updateColumnCount = 0;
                for(Property property:entity.properties){
                    if(property.id){
                        continue;
                    }
                    if(entity.uniqueProperties.contains(property)){
                        continue;
                    }
                    updateColumnCount++;
                }
                if(updateColumnCount==0){
                    throw new IllegalArgumentException("指定实体类字段全部为id字段或者唯一约束字段!实体类:"+entity.clazz.getName());
                }
            }break;
            case UpdateById:{
                if(null==entity.id){
                    throw new UnsupportedOperationException("指定实体类未指定id字段!实体类:"+entity.clazz.getName());
                }
            }break;
        }
    }
}
